// Copyright 2019 Hackware SpA <human@hackware.cl>
// This file is part of "Hackware Userland" and licensed under the terms
// of the GNU Affero General Public License version 3, or (at your option)
// a later version. You should have received a copy of this license along
// with the software. If not, see <https://www.gnu.org/licenses/>.

export default class Fetcher {
  constructor(haweseEndpoint) {
    this.haweseEndpoint = haweseEndpoint;
  }

  haweseGet(path, queryParams = {}, headers = {}, processResponse = true) {
    const strQueryParams = Object.entries(queryParams).length
      ? `?${(new URLSearchParams(queryParams)).toString()}`
      : '';

    return fetch(`${this.haweseEndpoint}${path}${strQueryParams}`, {
      method: 'GET',
      mode: 'cors',
      credentials: 'include',
      headers,
    }).then(response => (processResponse ? Fetcher.haweseProcessResponse(response) : response));
  }

  hawesePost(path, bodyParams = {}, headers = {}, processResponse = true) {
    let jsonBodyParams;
    if (bodyParams instanceof HTMLFormElement) {
      jsonBodyParams = Fetcher.formToObject(bodyParams);
    } else {
      jsonBodyParams = bodyParams;
    }
    jsonBodyParams = JSON.stringify(jsonBodyParams);

    const localHeaders = {
      ...{ 'Content-Type': 'application/json' },
      ...headers,
    };

    return fetch(`${this.haweseEndpoint}${path}`, {
      method: 'POST',
      mode: 'cors',
      credentials: 'include',
      headers: localHeaders,
      body: jsonBodyParams,
    }).then(response => (processResponse ? Fetcher.haweseProcessResponse(response) : response));
  }

  static haweseProcessResponse(response) {
    if ([401, 403].includes(response.status)) {
      // I'd like to do something else here, but this class has to do with
      // fetching things, not handling authentication nor redirecting with
      // the router. So I'll just dump an error to the console.
      // Something like this is done in the router.js:beforeEach
      throw new Error(`${response.statusText} request to ${response.url}`);
    }
    return response.json();
  }

  // Return an object from a form element (such as event.target)
  static formToObject(formElement) {
    const object = {};
    (new FormData(formElement)).forEach((value, key) => {
      object[key] = value;
    });
    return object;
  }
}
